package com.leyou.order.utils;

import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayUtil;
import com.leyou.common.enums.ExceptionEnum;
import com.leyou.common.exception.LyException;
import com.leyou.order.config.PayProperties;
import com.leyou.order.enums.OrderStatusEnum;
import com.leyou.order.enums.PayStateEnum;
import com.leyou.order.mapper.OrderMapper;
import com.leyou.order.mapper.OrderStatusMapper;
import com.leyou.order.pojo.Order;
import com.leyou.order.pojo.OrderStatus;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import static com.github.wxpay.sdk.WXPayConstants.FAIL;
import static com.github.wxpay.sdk.WXPayConstants.SignType.HMACSHA256;
import static com.github.wxpay.sdk.WXPayConstants.SignType.MD5;

@Slf4j
public class WxPayHelper {
    // 配置
    private PayProperties payProperties;

    // 支付工具
    private WXPay wxPay;

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private OrderStatusMapper orderStatusMapper;

    public WxPayHelper(PayProperties payProperties) {
        this.payProperties = payProperties;
        this.wxPay = new WXPay(payProperties, HMACSHA256);
    }

    public String createOrder(Long orderId, Long totalPay, String desc) {
        try {
            Map<String, String> data = new HashMap<>();
            // 商品描述
            data.put("body", desc);
            // 订单号
            data.put("out_trade_no", orderId.toString());
            //货币
            data.put("fee_type", "CNY");
            //金额，单位是分
            data.put("total_fee", totalPay.toString());
            //调用微信支付的终端IP
            data.put("spbill_create_ip", "127.0.0.1");
            //回调地址
            data.put("notify_url", payProperties.getNotifyUrl());
            // 交易类型为扫码支付
            data.put("trade_type", "NATIVE");
            // 发起请求,获取结果
            Map<String, String> result = wxPay.unifiedOrder(data);
            // 处理结果
            // 校验通信标识-返回状态码 和 返回业务码
            isSuccess(result);
            // 校验签名
            isValidSign(result);

            // 下单成功，获取支付链接
            String url = result.get("code_url");
            return url;
        } catch (Exception e) {
            log.error("【微信下单】创建预交易订单异常失败", e);
            return null;
        }
    }

    public PayStateEnum queryPayState(Long orderId) {
        try {
            // 组织请求参数
            Map<String, String> data = new HashMap<>();
            // 订单号
            data.put("out_trade_no", orderId.toString());
            // 查询状态
            Map<String, String> result = wxPay.orderQuery(data);
            // 校验状态
            isSuccess(result);
            // 校验签名
            isValidSign(result);
            // 校验金额
            String stringTotalFee = result.get("total_fee");
            String stringOutTradeNo = result.get("out_trade_no");
            if (StringUtils.isEmpty(stringTotalFee) || StringUtils.isEmpty(stringOutTradeNo)) {
                throw new LyException(ExceptionEnum.INVALID_ORDER_PARAM);
            }

            // 3.1 获取结果中的金额
            Long totalFee = Long.valueOf(stringTotalFee);

            // 3.2 获取订单金额
            Order order = orderMapper.selectByPrimaryKey(orderId);
            Long actualPay = /*order.getActualPay()*/ 1L;
            if (actualPay != totalFee) {
                // 金额不符
                throw new LyException(ExceptionEnum.INVALID_ORDER_PARAM);
            }

            String state = result.get("trade_state");
            if ("SUCCESS".equals(state)) {
                // 支付成功
                // 修改订单状态
                OrderStatus orderStatus = new OrderStatus();
                orderStatus.setOrderId(orderId);
                orderStatus.setStatus(OrderStatusEnum.PAY_UP.getStatus());
                orderStatus.setPaymentTime(new Date());
                int count = orderStatusMapper.updateByPrimaryKeySelective(orderStatus);
                if (count != 1) {
                    throw new LyException(ExceptionEnum.UPDATE_ORDER_STATUS_ERROR);
                }
                return PayStateEnum.SUCCESS;
            }

            if ("NOTPAY".equals(state) || "USERPAYING".equals(state)) {
                return PayStateEnum.NOT_PAY;
            }

            return PayStateEnum.FAIL;

        } catch (Exception e) {
            return PayStateEnum.NOT_PAY;
        }
    }

    public void isValidSign(Map<String, String> result) {
        try {
            // 校验签名
            boolean signatureValid1 = WXPayUtil.isSignatureValid(result, payProperties.getKey(), HMACSHA256);
            boolean signatureValid2 = WXPayUtil.isSignatureValid(result, payProperties.getKey(), MD5);
            if (!signatureValid1 && !signatureValid2) {
                throw new LyException(ExceptionEnum.WX_SIGNATURE_VALID);
            }
        } catch (Exception e) {
            throw new LyException(ExceptionEnum.WX_SIGNATURE_VALID);
        }
    }

    public void isSuccess(Map<String, String> result) {
        // 校验通信标识-返回状态码
        String returnCode = result.get("return_code");
        if (FAIL.equals(returnCode)) {
            log.error("[微信支付] 微信统一下单返回状态码失败,失败原因: {}", result.get("return_msg"));
            throw new LyException(ExceptionEnum.WX_CREATE_ORDER_ERROR);
        }
        // 校验返回业务码
        String resultCode = result.get("result_code");
        if (FAIL.equals(resultCode)) {
            log.error("[微信支付] 微信统一下单返回业务结果失败,错误代码: {},错误代码描述: {}", result.get("err_code"), result.get("err_code_des"));
            throw new LyException(ExceptionEnum.WX_CREATE_ORDER_ERROR);
        }
    }
}
